package com.cblz.bd.server.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cblz.bd.common.core.constant.BdAdminConstant;
import com.cblz.bd.common.core.entity.BaSecurityDataRecycle;
import com.cblz.bd.common.core.exception.BdAdminException;
import com.cblz.bd.common.core.utils.BdAdminUtil;
import com.cblz.bd.server.core.mapper.BaSecurityDataRecycleMapper;
import com.cblz.bd.server.core.service.BaSecurityDataRecycleService;
import io.vavr.Tuple;
import io.vavr.Tuple2;
import io.vavr.Tuple3;
import io.vavr.control.Option;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author yanjieping
 * @description 针对表【ba_security_data_recycle(回收规则表)】的数据库操作Service实现
 * @createDate 2022-11-04 15:09:53
 */
@Slf4j
@Service("baSecurityDataRecycleService")
@RequiredArgsConstructor
public class BaSecurityDataRecycleServiceImpl extends ServiceImpl<BaSecurityDataRecycleMapper, BaSecurityDataRecycle>
        implements BaSecurityDataRecycleService {
    // 数据库名
    private static final String BD_ADMIN = "bd_admin";
    private final ApplicationContext applicationContext;

    /**
     * 查询
     *
     * @param wrapperBaSecurityDataRecycleTuple3
     * @return
     */
    @Override
    public Map<String, Object> index(Tuple3<Page<BaSecurityDataRecycle>, QueryWrapper<BaSecurityDataRecycle>, Object> wrapperBaSecurityDataRecycleTuple3) {
        Page<BaSecurityDataRecycle> page = wrapperBaSecurityDataRecycleTuple3._1;
        QueryWrapper<BaSecurityDataRecycle> queryWrapper = wrapperBaSecurityDataRecycleTuple3._2;

        Page<BaSecurityDataRecycle> dataRecyclePage = this.page(page, queryWrapper);

        return BdAdminUtil.pageResult(dataRecyclePage, "在此定义需要回收的数据，实现数据自动统一回收");
    }

    /**
     * 操作前查询（获取所有数据库表名和DELETE的控制器）
     *
     * @return 所有数据库表名和DELETE的控制器
     */
    @Override
    public Tuple2<Map<String, String>, Map<String, String>> queryBeforeAnOperation() {
        /*
         拿到数据所有表名
         */
        Map<String, String> tablesMap = new HashMap<>();
        Option.of(this.baseMapper.getAllTableInfo(BD_ADMIN)).getOrElseThrow(() -> {
            throw new BdAdminException("找不到数据表名信息");
        }).stream().parallel().forEach(allTables ->
                tablesMap.put(allTables.getTableName(), allTables.getTableName() + " - " + allTables.getTableComment())
        );

        /*
         拿到所有DELETE的控制器路径
         */
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        Map<String, String> controllerMap = new HashMap<>();
        map.keySet().stream().filter(requestMappingInfo -> {
            // 请求方式
            Set<String> methodName = requestMappingInfo.getMethodsCondition().getMethods().stream().map(Enum::name).collect(Collectors.toSet());
            return methodName.contains("DELETE");
        }).forEach(requestMappingInfo -> {
            assert requestMappingInfo.getPathPatternsCondition() != null;

            Set<String> patternValues = requestMappingInfo.getPathPatternsCondition().getPatternValues();
            patternValues.forEach(s -> {
                controllerMap.put(s, s);
            });
        });

        return Tuple.of(tablesMap, controllerMap);
    }

    /**
     * 拿到指定表对应的主键列
     *
     * @param tableName 表名
     * @return 主键列
     */
    @Override
    public String getPrimaryKeyString(String tableName) {
        return String.join(BdAdminConstant.SYSTEM_COMMA.getVal(), Option.of(this.baseMapper.getPrimaryKeyString(BD_ADMIN, tableName)).getOrElseThrow(() -> {
            throw new BdAdminException("该表没有查询到主键列");
        }));
    }
}




